package me.qi.kancha.security.grant.custom.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import me.qi.kancha.applet.AppletLoginSdk;
import me.qi.kancha.mapper.AccountMapper;
import me.qi.kancha.security.grant.custom.CustomAuthServiceTag;
import me.qi.kancha.dto.core.AccountDTO;
import me.qi.kancha.dto.enums.AccountStatus;
import me.qi.kancha.dto.enums.AccountType;
import me.qi.kancha.security.grant.custom.CustomAuthService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

/**
 * jscode认证服务实现
 *
 * @author sun
 * @date 2019/10/18 11:26
 */
@Component
@CustomAuthServiceTag
public class WxJscodeAuthorizationService implements CustomAuthService {

    private static final String GRANT_TYPE = "jscode";

    private final AccountMapper accountMapper;

    private final AppletLoginSdk appletLoginSdk;

    public WxJscodeAuthorizationService(AccountMapper accountMapper, AppletLoginSdk appletLoginSdk) {
        this.accountMapper = accountMapper;
        this.appletLoginSdk = appletLoginSdk;
    }

    @Override
    public String getGrantType() {
        return GRANT_TYPE;
    }

    @Override
    public Authentication authorization(OAuth2Request oAuth2Request) throws InvalidGrantException {
        //微信登录
        String appId = oAuth2Request.getClientId();
        String jscode = oAuth2Request.getRequestParameters().get(GRANT_TYPE);
        if (ObjectUtils.isEmpty(jscode)) {
            throw new InvalidGrantException("jscode验证模式必须传入jscode参数");
        }
        AppletLoginSdk.WXUserInfo wxUserInfo = appletLoginSdk.appletLogin(appId, jscode);
        //微信用户是否存在appid & openid
        String u = String.format("%s:%s", appId, wxUserInfo.getOpenid());
        LambdaQueryWrapper<AccountDTO> lqw = new LambdaQueryWrapper<>();
        AccountDTO accountDTO = accountMapper.selectOne(lqw.eq(AccountDTO::getUsername, u));
        if (accountDTO == null) {
            //不存在新增
            accountDTO = new AccountDTO();
            accountDTO.setUsername(u);
            accountDTO.setType(AccountType.APPLET);
            accountDTO.setStatus(AccountStatus.NORMAL);
            accountMapper.insert(accountDTO);
        }
        accountDTO.setUnionid(wxUserInfo.getUnionid());
        return new UsernamePasswordAuthenticationToken(accountDTO, null, null);
    }

}
